<?php
if(!interface_exists('XPartitionStrategy', false)){
	require(dirname(__FILE__).DIRECTORY_SEPARATOR.'XPartitionStrategy.php');
}
class XRangePartitionStrategy implements XPartitionStrategy{
	private $ranges = array();
	private $splitChar = ';';
	private $betweenChar = '-';
	private $valueChar = ':';
	
	public function partition(XAnnotation $annotations, $value){
		if(count($this->ranges) == 0){			
			$this->_loadRanges($annotations);
		}
		$name = $annotations->get('Partition.name');
		foreach($this->ranges as $range){
			if($value>=$range['min'] && $value<=$range['max']){
				return $name.'_'.$range['index'];
			}
		}
		$range = x_array_tail($this->ranges);
		return $name.'_'.$range['index'];
	}
	
	public function allPartitions(XAnnotation $annotations){
		if(count($this->ranges) == 0){			
			$this->_loadRanges($annotations);
		}		
		$name = $annotations->get('Partition.name');
		$tables = array();
		foreach($this->ranges as $value){
			$tables[] = $name.'_'.$value['index'];
		}
		return $tables;
	}

	private function _loadRanges(XAnnotation $annotations){
		$range = $annotations->get('Strategy.range');		
		if(is_null($range)){
			throw new XORMException("Partition Range Strategy requires correct range in annotations.");
		}
		$splits = preg_split("/{$this->splitChar}/i", trim($range, " \"'"));
		foreach($splits as $split){
			preg_match("/(\w+){$this->valueChar}(\w+){$this->betweenChar}(\w+)/i", $split, $match);
			if(!isset($match[1])
				|| !isset($match[2])
				|| !isset($match[3])){
				continue;
			}
			$this->ranges[$match[1]] = array(
				'index' => $match[1],
				'min' => $match[2],
				'max' => $match[3],
			);
		}
		if(count($this->ranges) == 0){
			throw new XORMException("Partition Range Strategy requires correct range in annotations.");
		}		
	}
	
	public function totalCount(XAnnotation $annotations){
		if(count($this->ranges) == 0){			
			$this->_loadRanges($annotations);
		}
		return count($this->ranges);
	}
	
	/**
	 * @param $valueChar the $valueChar to set
	 */
	public function setValueChar($valueChar) {
		$this->valueChar = $valueChar;
		return $this;
	}

	/**
	 * @param $betweenChar the $betweenChar to set
	 */
	public function setBetweenChar($betweenChar) {
		$this->betweenChar = $betweenChar;
		return $this;
	}

	/**
	 * @param $splitChar the $splitChar to set
	 */
	public function setSplitChar($splitChar) {
		$this->splitChar = $splitChar;
		return $this;
	}
}
?>